package array_queue

type MQueue struct {
	IData []interface{}
	ISize int64
	ILen  int64
	IHead int64
	ITail int64
}

func NewMQueue(size int64) *MQueue {
	return &MQueue{
		IData: make([]interface{}, size),
		ILen:  0,
		ISize: size,
		IHead: 0,
		ITail: 0,
	}
}

func (q *MQueue) Length() int64 {
	return q.ILen
}

func (q *MQueue) IsEmpty() bool {
	return q.ILen == 0
}

func (q *MQueue) IsFull() bool {
	return q.ILen == q.ISize
}

func (q *MQueue) RPush(elem interface{}) bool {
	if q.IsFull() {
		return false
	}
	q.IData[q.IHead] = elem
	q.IHead = (q.IHead + 1) % q.ISize
	q.ILen++
	return true
}

func (q *MQueue) LPop() (interface{}, bool) {
	if q.IsEmpty() {
		return nil, false
	}
	tempElem := q.IData[q.ITail]
	q.ITail = (q.ITail + 1) % q.ISize
	q.ILen--
	return tempElem, true
}

func (q *MQueue) Traverse(callback func(elem interface{})) {
	var ii int64
	for ii = q.ITail; ii < q.ITail+q.ILen; ii++ {
		callback(q.IData[ii%q.ISize])
	}
}
